import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class FetionMessageProcessor extends Thread {

	private Socket socket;
	private OutputStream flexOut = null;
	private InputStream flexIn = null;
	private String RETURN = "\r\n";
	private String mobile = null;
	private String fetionId = null;
	private String password = null;
	public String fetionUri;
	public String sipc_proxy;
	public String nonce;
	public int seq = 1;
	public FetionMessage fm;
	public FetionMessage fmHttp;
	public boolean flag = true;

	public FetionMessageProcessor(Socket socket) {
		this.socket = socket;
	}

	public void connect() {
		try {
			flexOut = socket.getOutputStream();
			flexIn = socket.getInputStream();
			start();
		} catch (Exception e) {
			e.printStackTrace();

		}
	}

	public byte[] readFlex() throws IOException {
		byte[] buffer = new byte[1024 * 1024];
		ByteArrayOutputStream bo = new ByteArrayOutputStream(10240);
		int c = 0;
		if (flexIn.available() > 0) {
			c = flexIn.read(buffer);
			{
				if (c > 0) {
					bo.write(buffer, 0, c);
				}
			}
		}

		return bo.toByteArray();
	}

	public void writeFlex(String data) throws IOException {
		flexOut.write(data.getBytes());
		flexOut.flush();

//		System.out
//				.println("))))))-----------------------------------------------------------------");
//		System.out.println(data);
//		System.out
//				.println("))))))--------------------------------------------------------------------");
	}

	public void run() {
		try {
			while (flag) {

				byte[] buffer = readFlex();
				if (buffer.length > 0) {
					String message = new String(buffer, "utf-8");
//					System.out
//							.println("((((((--------------------------------------------------------------------");
//					System.out.println(message);
//					System.out
//							.println("((((((--------------------------------------------------------------------");

					if (message != null) {
						message = message.trim();
						if (message.equals("<policy-file-request/>")) {
							String xml = "<cross-domain-policy>";
							xml += "<allow-access-from domain=\"*\" to-ports=\"*\" />";
							xml += "<allow-access-from domain=\"*\"/>";
							xml += "</cross-domain-policy>";
							writeFlex(xml + "\0");
							System.out
									.println("Response the policy file to client...");

						} else if (message.startsWith("<USERQUIT/>")) {
							fm.closeSocket();
							fm = null;
							break;
						} else if (message.startsWith("<FetionUser>")) {
							fm = new FetionMessage(this);
							String[] infos = message.split("#");
							mobile = infos[1].substring(2);
							fetionId = infos[2].substring(2);
							password = infos[3].substring(2);

							if (mobile != null) {
								fm.mobile = mobile;
							}
							if (fetionId != null) {
								fm.fetionId = fetionId;
							}
							if (password != null) {
								fm.password = password;
							}
							fm.getFetionUri();
							if (fm.fetionUri == null) {
								String error = "I_LOGIN_FAIL#000000000#I:32 "
										+ "#00000000#00000000";
								writeFlex(error);
								socket.close();
								fm = null;
								flag = false;
								return;
							}
							fm.getSipcProxy();
							fm.openSocket();
							fm.getNonce();
							fm.sendResponse();
							fm.subPresence();
							fm.start();

							fm.getContactList();

							String data = null;
							if (fm.fetionUri != null) {
								data = "I_LOGIN_OK#" + fm.fetionId + "#I:31 "
										+ "#" + fm.fetionUri + "#" + fm.mobile;
							} else {
								data = "I_LOGIN_FAIL#" + fm.fetionId + "#I:32 "
										+ "#" + fm.fetionUri + "#" + fm.mobile;
							}
							writeFlex(data);

							System.out.println("<FetionUser>=" + data);

							// fm.getPersonalInfo(fetionId);
							// fm.getContactList();

							fm.setFmp(this);

						} else if (message
								.startsWith("<SENDMSG fetion.com.cn SIP-C/2.0>")) {
							String[] data = message.split("#MSG@");
							if (data[3] != null) {
								if (!"".equals(data[3])) {
									fm.sendMsg(data[3], data[2], data[1]);
								}
							}
						//	var data:String = "<SENDMSG fetion.com.cn SIP-C/2.0>#MSG@"+n+"#MSG@"+dstUri+"#MSG@"+message;
						} else if (message.startsWith("<GetPicCodeReg>")) {
							fmHttp = new FetionMessage();
							fmHttp.getPicCode();
							String data = "<GetPicCodeReg>" + "@#"
									+ fmHttp.picId + "@#" + fmHttp.picContent;
							System.out.println("<GetPicCodeReg>=" + data);
							writeFlex(data);
						} else if (message.startsWith("<GetPicCodePwd>")) {
							fmHttp = new FetionMessage();
							fmHttp.getPicCode();
							String data = "<GetPicCodePwd>" + "@#"
									+ fmHttp.picId + "@#" + fmHttp.picContent;
							System.out.println("<GetPicCodePwd>=" + data);
							writeFlex(data);
						} else if (message.startsWith("<GetSmsCode>")) {
							fmHttp = new FetionMessage();
							String[] data = message.split("#");
							fmHttp.tmpMobile = data[1];
							fmHttp.picCode = data[2];
							fmHttp.picId = data[3];
							fmHttp.getSmsCode();
							System.out.println("<GetSmsCode>="
									+ fmHttp.tmpMobile + " " + fmHttp.picCode);
						} else if (message.startsWith("<UpdatePwd>")) {
							fmHttp = new FetionMessage();
							String[] data = message.split("#");
							fmHttp.tmpMobile = data[1];
							fmHttp.smsCode = data[2];
							fmHttp.newPassword = data[3];
							fmHttp.updatePwd();
							System.out.println("<UpdatePwd>="
									+ fmHttp.tmpMobile + " " + fmHttp.smsCode
									+ " " + fmHttp.newPassword);
						} else if (message.startsWith("<RegUser>")) {
							fmHttp = new FetionMessage();
							String[] data = message.split("#");
							fmHttp.tmpMobile = data[1];
							fmHttp.smsCode = data[2];
							fmHttp.newPassword = data[3];
							String feteionIdReg = fmHttp.regUser();

							System.out.println("<RegUser>=" + fmHttp.tmpMobile
									+ " " + fmHttp.smsCode + " "
									+ fmHttp.newPassword);

							writeFlex("<RegUserResult>@#" + feteionIdReg);
						} else {

							fm.write(message);
							// fm.addMessage(message);

						}
					}
				}

				this.sleep(100L);
			}
		} catch (Exception e) {
			e.printStackTrace();

		}
	}

	public String getProxyIp(String proxy) {
		return proxy.substring(0, proxy.indexOf(":"));
	}

	public int getProxyPort(String proxy) {
		return Integer.parseInt(proxy.substring(proxy.indexOf(":") + 1));
	}

	public String getFetionId(String fetionUri) {
		int p1 = fetionUri.indexOf(":");
		int p2 = fetionUri.indexOf("@");
		return fetionUri.substring(p1 + 1, p2);
	}

	public String findNonce(String src) {
		String rst = null;
		String flag = "nonce=\"";
		int p1 = src.indexOf(flag);
		int p2 = src.lastIndexOf("\"");
		rst = src.substring(p1 + flag.length(), p2);
		System.out.println("Nonce-->" + rst);
		return rst;
	}

}
